#include <stdio.h>
#include "head.h"
#include "Control.h"
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/un.h>
#include <time.h>

#define FAIL "fail"
#define SUCCESS "success"

struct sockaddr_in client_addr;



void getDate(char* date){

	time_t t;
	struct tm *ptm;

	t = time(NULL);
	ptm = localtime(&t);
	sprintf(date, "%d-%d-%d %d:%d:%d", ptm->tm_year + 1900, ptm->tm_mon + 1,
			ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);

	return;
}

void save_history(char*name, char* action){
	
	HistoryInfo history_info;
	strcpy(history_info.name, name);
	strcpy(history_info.action, action);
	getDate(history_info.date);

	add_history(&history_info);

	return;
}

#if 1
void do_regist(int con_fd, Msg* p_msg){
	int ret;
	char buf[256] = {0};

	if(strlen(p_msg->user_info.name) > 19 || strlen(p_msg->user_info.passwd) > 19){
		strcpy(p_msg->buf, FAIL);
		send(con_fd, p_msg, sizeof(Msg), 0);
		return;
	}
#if 0
	p_msg->user_info.age = 24;
	p_msg->user_info.year = 0;
	p_msg->user_info.salary = 4000;
	p_msg->user_info.sex = 'm';
	p_msg->user_info.managedr = 0;
#endif
	strcpy(p_msg->user_info.department, "worker");

	ret = regist(p_msg->user_info.name, p_msg->user_info.passwd);
	if(ret < 0){
		strcpy(p_msg->buf, FAIL);
	}
	strcpy(p_msg->buf, SUCCESS);
	
	send(con_fd, p_msg, sizeof(Msg), 0);
	return;
}

void do_login(int con_fd, Msg* p_msg){
	int ret;
	char buf[256] = {0};
	if(strlen(p_msg->user_info.name) > 19 || strlen(p_msg->user_info.passwd) > 19){
		strcpy(p_msg->buf, FAIL);
		send(con_fd, p_msg, sizeof(Msg), 0);
		return;
	}

	ret = login(p_msg->user_info.name, p_msg->user_info.passwd);
	if(ret < 0){
		strcpy(p_msg->buf, "loginfail");
	}else{
		strcpy(p_msg->buf, "loginok");
	}
	
	query_user_info_by_name(p_msg->user_info.name, &(p_msg->user_info));
	UserInfo * user = &(p_msg->user_info);

	send(con_fd, p_msg, sizeof(Msg), 0);

	return;
}

void do_quit(int con_fd){
	printf("client %s disconnect\n", inet_ntoa(client_addr.sin_addr));
	close(con_fd);
	exit(1);
}

void do_select_user(int con_fd, Msg* p_msg){
	int ret;

	if(strlen(p_msg->user_info.name) > 19){
		strcpy(p_msg->buf, FAIL);
		send(con_fd, p_msg, sizeof(Msg), 0);
	}

	ret = query_user_info_by_name(p_msg->user_info.name, &(p_msg->user_info));
	if(ret < 0){
		strcpy(p_msg->buf, FAIL);
	}
	strcpy(p_msg->buf, SUCCESS);
	
	send(con_fd, p_msg, sizeof(Msg), 0);
	
	return;
}

void do_change_passwd(int con_fd, Msg* p_msg){
	int ret;

	if(strlen(p_msg->user_info.name) > 19 || strlen(p_msg->user_info.passwd) > 19){
		strcpy(p_msg->buf, FAIL);
		send(con_fd, p_msg, sizeof(Msg), 0);
		return;
	}

	ret = update_passwd(p_msg->user_info.name, p_msg->user_info.passwd);
	if(ret < 0){
		strcpy(p_msg->buf, FAIL);
	}
	strcpy(p_msg->buf, SUCCESS);
	
	send(con_fd, p_msg, sizeof(Msg), 0);

	return;

}

void do_update_user_info(int con_fd, Msg* p_msg){
	int ret;

	ret = update_user_info(&(p_msg->user_info));
	if(ret < 0){
		strcpy(p_msg->buf, FAIL);
	}
	strcpy(p_msg->buf, SUCCESS);
	
	send(con_fd, p_msg, sizeof(Msg), 0);
}

void do_add_user(int con_fd, Msg* p_msg){
	int ret;

	ret = add_user_info(&(p_msg->user_info));
	if(ret < 0){
		strcpy(p_msg->buf, FAIL);
	}
	strcpy(p_msg->buf, SUCCESS);
	
	send(con_fd, p_msg, sizeof(Msg), 0);
	
	return;
}

void do_delete_user(int con_fd, Msg* p_msg){
	int ret;

	ret = delete_user(p_msg->user_info.name);
	if(ret < 0){
		strcpy(p_msg->buf, FAIL);
	}
	strcpy(p_msg->buf, SUCCESS);
	
	send(con_fd, p_msg, sizeof(Msg), 0);

	return;
}

void do_query_all_user(int con_fd, Msg* p_msg){
	int i;
	int ret;
	int count;
	UserInfo* users;

	count = get_user_count();
	if(count <= 0){
		strcpy(p_msg->buf, "over");
		send(con_fd, p_msg, sizeof(Msg), 0);
		return;
	}

	users = (UserInfo*)malloc(sizeof(UserInfo) * count);
	ret = query_all_user_info(users, count);

	for(i = 0; i < count; i++){
		memcpy(&(p_msg->user_info), (users + i), sizeof(UserInfo));
		strcpy(p_msg->buf, " ");
		send(con_fd, p_msg, sizeof(Msg), 0);
		recv(con_fd, p_msg, sizeof(Msg), 0);
	}

	strcpy(p_msg->buf, "over");
	send(con_fd, p_msg, sizeof(Msg), 0);

	free(users);

	return;
}

void do_query_user(int con_fd, Msg* p_msg){
	int ret;

	if(strlen(p_msg->user_info.name) > 19){
		strcpy(p_msg->buf, FAIL);
		send(con_fd, p_msg, sizeof(Msg), 0);
	}

	ret = query_user_info_by_name(p_msg->user_info.name, &(p_msg->user_info));
	if(ret < 0){
		strcpy(p_msg->buf, FAIL);
	}
	strcpy(p_msg->buf, SUCCESS);
	
	send(con_fd, p_msg, sizeof(Msg), 0);
	
	return;
}

void do_query_all_history(int con_fd, Msg* p_msg){
	int i;
	int ret;
	int count;
	HistoryInfo* history_arr;

	count = get_history_count();
	if(count <= 0){
		strcpy(p_msg->buf, "over");
		send(con_fd, p_msg, sizeof(Msg), 0);
		return;
	}

	history_arr = (HistoryInfo*)malloc(sizeof(HistoryInfo) * count);
	query_all_history(history_arr, count);

	for(i = 0; i < count; i++){
		memcpy(&(p_msg->history_info), (history_arr + i), sizeof(HistoryInfo));
		strcpy(p_msg->buf, " ");
		send(con_fd, p_msg, sizeof(Msg), 0);
		recv(con_fd, p_msg, sizeof(Msg), 0);
	}

	strcpy(p_msg->buf, "over");
	send(con_fd, p_msg, sizeof(Msg), 0);

	free(history_arr);

	return;
}

void do_query_user_history(int con_fd, Msg* p_msg){
	int i;
	int ret;
	int count;
	HistoryInfo* history_arr;

	count = get_history_by_name_count(p_msg->user_info.name);
	if(count <= 0){
		strcpy(p_msg->buf, "over");
		send(con_fd, p_msg, sizeof(Msg), 0);
		return;
	}

	history_arr = (HistoryInfo*)malloc(sizeof(HistoryInfo) * count);
	query_history_by_name(p_msg->user_info.name, history_arr, count);

	for(i = 0; i < count; i++){
		memcpy(&(p_msg->history_info), (history_arr + i), sizeof(HistoryInfo));
		//printf("%s  %s  %s\n", p_msg->history_info.name, p_msg->history_info.date, p_msg->history_info.action);
		strcpy(p_msg->buf, " ");
		send(con_fd, p_msg, sizeof(Msg), 0);
		recv(con_fd, p_msg, sizeof(Msg), 0);
	}

	strcpy(p_msg->buf, "over");
	send(con_fd, p_msg, sizeof(Msg), 0);

	free(history_arr);

	return;
}
#endif

int main(int argc, const char *argv[])
{
	if(argc < 2){
		printf("please input <port>\n");
		exit(1);
	}

	int ret;
	int pid;
	int con_fd;
	int sock_fd;
	Msg msg = {0};
	char buf[1024];
	socklen_t size = sizeof(struct sockaddr_in);
	struct sockaddr_in serv_addr;

	init();

	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	if(sock_fd < 0){
		perror("fail to socket()");
		exit(1);
	}

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = inet_addr(IP);
	serv_addr.sin_port = htons(atoi(argv[1]));
	ret = bind(sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
	if(ret < 0){
		perror("fail to bind()");
		exit(1);
	}

	ret = listen(sock_fd, 5);
	if(ret < 0){
		perror("fail to listen()");
		exit(1);
	}

	while(1){
		con_fd = accept(sock_fd, (struct sockaddr*)&client_addr, &size);
		printf("client %s Connected\n", inet_ntoa(client_addr.sin_addr));
		if(con_fd < 0){
			perror("fail to accept");
			exit(1);
		}

		pid = fork();
		if(pid == 0){
			break;
		}
	}

	if(pid > 0){
		exit(0);
	}

	while(1){
		ret = recv(con_fd, &msg, sizeof(Msg), 0);
		if(ret <= 0){
			do_quit(con_fd);
			exit(1);
		}

		switch(msg.cmd){
			case 1:
				save_history(msg.user_info.name, "reigst");
				do_regist(con_fd, &msg);
				break;

			case 2:
				save_history(msg.user_info.name, "login");
				do_login(con_fd, &msg);
				break;

			case 3:
				do_quit(con_fd);
				break;

			case 4:
				save_history(msg.user_info.name, "select self");
				do_select_user(con_fd, &msg);
				break;

			case 5:
				save_history(msg.user_info.name, "change passwd");
				do_change_passwd(con_fd, &msg);
				break;

			case 6:
				save_history(msg.user_info.name, "update user info");
				do_update_user_info(con_fd, &msg);
				break;

			case 7:
				save_history(msg.user_info.name, "query_user_history");
				do_query_user_history(con_fd, &msg);
				break;

			case 8:
				save_history(msg.user_info.name, "add_user");
				do_add_user(con_fd, &msg);
				break;

			case 9:
				save_history(msg.user_info.name, "update_user_info");
				do_update_user_info(con_fd, &msg);
				break;
				
			case 10:
				save_history(msg.user_info.name, "delete_user");
				do_delete_user(con_fd, &msg);
				break;

			case 11:
				save_history(msg.user_info.name, "query_all_user");
				do_query_all_user(con_fd, &msg);
				break;

			case 12:
				save_history(msg.user_info.name, "query_user");
				do_query_user(con_fd, &msg);
				break;
			case 13:
				save_history(msg.user_info.name, "query_all_history");
				do_query_all_history(con_fd, &msg);
				break;

			case 14:
				do_query_user_history(con_fd, &msg);
				break;

		}
	}

	return 0;
}
